package net.plentz.tagger.ui.widgets;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.plentz.tagger.ui.listeners.events.AbstractEvent;
import net.plentz.tagger.ui.listeners.events.AbstractEvent.Action;

import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Composite;

public abstract class AbstractWidget {

	public static final int DEFAULT_FORM_MARGIN_WIDTH = 5;
	public static final int DEFAULT_FORM_MARGIN_HEIGHT = 5;

	protected Map<Action, List<AbstractWidget>> listeners;

	public AbstractWidget() {
		this.listeners = new HashMap<Action, List<AbstractWidget>>();
	}

	public abstract Composite render(Composite parent, int flags);

	public void addListener(Action action, AbstractWidget widget) {
		if (!this.listeners.containsKey(action)) {
			this.listeners.put(action, new ArrayList<AbstractWidget>());
		}
		this.listeners.get(action).add(widget);
	}

	public <T> void broadcastEvent(AbstractEvent<T> event) {
		List<AbstractWidget> widgets = this.listeners.get(event.getAction());
		List<Integer> badWidgetIndexes = new ArrayList<Integer>();
		for (int i = 0, il = widgets.size(); i < il; i++) {
			if (widgets.get(i) == null) {
				badWidgetIndexes.add(i);
			} else {
				widgets.get(i).invokeEvent(event);
			}
		}
		for (int i = badWidgetIndexes.size() - 1; i >= 0; i--) {
			widgets.remove(badWidgetIndexes.get(i));
		}
	}

	protected abstract <T> void invokeEvent(AbstractEvent<T> event);

	protected static final FormLayout getDefaultFormLayout() {
		FormLayout layout = new FormLayout();
		layout.marginWidth = AbstractWidget.DEFAULT_FORM_MARGIN_WIDTH;
		layout.marginHeight = AbstractWidget.DEFAULT_FORM_MARGIN_HEIGHT;
		return layout;
	}

}
